home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / sviluppo / svilupp2 / gmsppr10.lha / Library.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  18KB  |  757 lines

  1. /****** gamesupport.library/--background-- *******************************
  2. *
  3. *    gamesupport.library offsers various functions for
  4. *    system-compliant, AUISG conforming games.
  5. *
  6. *    Some things should be noted:
  7. *    a) don't access gamesupport.library-maintained files (such
  8. *       as high score tables) yourself. gamesupport.library uses
  9. *       various locking techniques to ensure proper operation
  10. *       with respect to multitasking and networked filesystems.
  11. *
  12. *    b) gamesupport.library uses various assigns to let the user
  13. *       override the default location for files. However,
  14. *       strange (although not fatal with respect to overall system
  15. *       operation) things might happen if you change these
  16. *       assigns "in the middle of a game". The intended usage
  17. *       is to setup any required assigns at boottime.
  18. *
  19. *    c) currently AmigaOS V39 (Release 3.0) or newer is required
  20. *
  21. *    d) there is no gamesupport memhandler. This is because you
  22. *       cannot call FreePooled() on a shared memory pool (as used
  23. *       by gamesupport.library) inside a memhandler. One of the
  24. *       many AmigaOS design problems.
  25. *
  26. *    e) gamesupport library ignores the starvation problem.
  27. *
  28. *************************************************************************/
  29.  
  30. #ifndef EXEC_INITIALIZERS_H
  31. #include <exec/initializers.h>
  32. #endif
  33.  
  34. #ifndef EXEC_LIBRARIES_H
  35. #include <exec/libraries.h>
  36. #endif
  37.  
  38. #ifndef DOS_DOSEXTENS_H
  39. #include <dos/dosextens.h>
  40. #endif
  41.  
  42. #ifndef GRAPHICS_GFXBASE_H
  43. #include <graphics/gfxbase.h>
  44. #endif
  45.  
  46. #ifndef INTUITION_INTUITIONBASE_H
  47. #include <intuition/intuitionbase.h>
  48. #endif
  49.  
  50. #include <proto/exec.h>
  51. #include <proto/dos.h>
  52. #include <proto/iffparse.h>
  53. #include <proto/intuition.h>
  54.  
  55. #include "Version.h"
  56.  
  57. /************************************************************************/
  58.  
  59. #include "Global.h"
  60.  
  61. /************************************************************************/
  62.  
  63. #include "StaticSavedsAsmD0A0A6.h"
  64. #include "StaticSavedsAsmA6.h"
  65. #include "StaticSaveds.h"
  66.  
  67. /************************************************************************/
  68.  
  69. const char LibName[]=LIBRARY_NAME;
  70. const char LibIDString[]=LIBRARY_NAME " " LIBRARY_VERSION_STR " (" LIBRARY_DATE ")";
  71.  
  72. static const struct
  73. {
  74.   UBYTE Table1[4];
  75.   UBYTE Table2[4];
  76.   UBYTE Table3[2]; char *LibName;
  77.   UBYTE Table4[4];
  78.   UBYTE Table5[2]; UWORD Table6[1];
  79.   UBYTE Table7[2]; UWORD Table8[1];
  80.   UBYTE Table9[2]; char *IDString;
  81.   UBYTE TableEnd;
  82. } DataTable=
  83. {
  84.   0xa0,OFFSET(Node,ln_Type),NT_LIBRARY,0,
  85.   0xa0,OFFSET(Node,ln_Pri),-5,0,
  86.   0x80,OFFSET(Node,ln_Name),LibName,
  87.   0xa0,OFFSET(Library,lib_Flags),LIBF_SUMUSED|LIBF_CHANGED,0,
  88.   0x90,OFFSET(Library,lib_Version),LIBRARY_VERSION,
  89.   0x90,OFFSET(Library,lib_Revision),LIBRARY_REVISION,
  90.   0x80,OFFSET(Library,lib_IdString),LibIDString,
  91.   0
  92. };
  93.  
  94. /************************************************************************/
  95.  
  96. STATIC_SAVEDS_ASM_A6_PROTO(struct GameSupportBase *,LibOpen,struct GameSupportBase *);
  97. STATIC_SAVEDS_ASM_A6_PROTO(BPTR,LibClose,struct GameSupportBase *);
  98. STATIC_SAVEDS_ASM_A6_PROTO(BPTR,LibExpunge,struct GameSupportBase *);
  99. static ULONG LibNull(void);
  100.  
  101. static const APTR LibFuncTable[]=
  102. {
  103.   (APTR)LibOpen,
  104.   (APTR)LibClose,
  105.   (APTR)LibExpunge,
  106.   (APTR)LibNull,
  107.  
  108. #include "FunctionTable.c"
  109.  
  110.   (APTR)-1
  111. };
  112.  
  113. /************************************************************************/
  114.  
  115. STATIC_SAVEDS_ASM_D0A0A6_PROTO(struct GameSupportBase *,LibInit,struct GameSupportBase *,BPTR,struct ExecBase *);
  116.  
  117. const APTR LibInitTable[4]=
  118. {
  119.   (APTR)sizeof(struct GameSupportBase),
  120.   (APTR)LibFuncTable,
  121.   (APTR)&DataTable,
  122.   (APTR)LibInit
  123. };
  124.  
  125. /************************************************************************/
  126. /*                                    */
  127. /* Some string constants required by several modules.            */
  128. /*                                    */
  129. /************************************************************************/
  130.  
  131. char IFFParseName[]="iffparse.library";
  132. char GameStuff[]="GAMESTUFF:";
  133. char ProgDir[]="PROGDIR:";
  134.  
  135. /************************************************************************/
  136.  
  137. struct ExecBase *SysBase;
  138. struct Library *UtilityBase;
  139. struct DosLibrary *DOSBase;
  140. struct GfxBase *GfxBase;
  141. struct Library *LocaleBase;
  142. struct IntuitionBase *IntuitionBase;
  143.  
  144. struct SignalSemaphore GameSupportSemaphore;
  145.  
  146. struct GameSupportBase *GameSupportBase;
  147.  
  148. static BPTR SegList;
  149. static struct SignalSemaphore BaseSemaphore;
  150. static ULONG BaseInitialized;
  151.  
  152. static void *MemoryPool;
  153. static struct SignalSemaphore MemorySemaphore;
  154.  
  155. /************************************************************************/
  156. /*                                    */
  157. /*                                    */
  158. /************************************************************************/
  159.  
  160. #if !defined(__GNUC__) || !defined(__OPTIMIZE__)
  161.  
  162. char *Stpcpy(char *Dest, const char *Source)
  163.  
  164. {
  165.   while ((*Dest++=*Source++))
  166.     ;
  167.   return Dest-1;
  168. }
  169.  
  170. #endif
  171.  
  172. /************************************************************************/
  173. /*                                    */
  174. /* Wrappers for some iffparse functions                    */
  175. /*                                    */
  176. /************************************************************************/
  177.  
  178. LONG (MyWriteChunkBytes)(struct Library *IFFParseBase, struct IFFHandle *IFFHandle, const void *Data, ULONG Size)
  179.  
  180. {
  181.   LONG Error;
  182.  
  183.   Error=WriteChunkBytes(IFFHandle,Data,Size);
  184.   if (Error==Size)
  185.     {
  186.       Error=0;
  187.     }
  188.   else if (Error>=0)
  189.     {
  190.       Error=IFFERR_WRITE;
  191.     }
  192.   return Error;
  193. }
  194.  
  195. /*----------------------------------------------------------------------*/
  196.  
  197. LONG (MyReadChunkBytes)(struct Library *IFFParseBase, struct IFFHandle *IFFHandle, void *Data, ULONG Size)
  198.  
  199. {
  200.   LONG Error;
  201.  
  202.   Error=ReadChunkBytes(IFFHandle,Data,Size);
  203.   if (Error==Size)
  204.     {
  205.       Error=0;
  206.     }
  207.   else if (Error>=0)
  208.     {
  209.       Error=IFFERR_READ;
  210.     }
  211.   return Error;
  212. }
  213.  
  214. /************************************************************************/
  215. /*                                    */
  216. /* Library init function.                        */
  217. /*                                    */
  218. /************************************************************************/
  219.  
  220. STATIC_SAVEDS_ASM_D0A0A6(struct GameSupportBase *,LibInit,struct GameSupportBase *,TheGameSupportBase,BPTR,TheSegList,struct ExecBase *,TheSysBase)
  221.  
  222. {
  223.   GameSupportBase=TheGameSupportBase;
  224.   SysBase=TheSysBase;
  225.   SegList=TheSegList;
  226.   InitSemaphore(&BaseSemaphore);
  227.   return TheGameSupportBase;
  228. }
  229.  
  230. /************************************************************************/
  231. /*                                    */
  232. /* Cleanup the library base.                        */
  233. /*                                    */
  234. /************************************************************************/
  235.  
  236. static void CleanupLibraryBase(struct GameSupportBase *GameSupportBase)
  237.  
  238. {
  239.   if (IntuitionBase!=NULL)
  240.     {
  241.       if (DOSBase!=NULL)
  242.     {
  243.       if (GfxBase!=NULL)
  244.         {
  245.           if (UtilityBase!=NULL)
  246.         {
  247.           if (GameSupportBase->LayersBase!=NULL)
  248.             {
  249.               if (GameSupportBase->KeymapBase!=NULL)
  250.             {
  251.               CloseLibrary(LocaleBase);
  252.               if (MemoryPool!=NULL)
  253.                 {
  254.                   DeletePool(MemoryPool);
  255.                 }
  256.               CloseLibrary(GameSupportBase->KeymapBase);
  257.             }
  258.               CloseLibrary(GameSupportBase->LayersBase);
  259.             }
  260.           CloseLibrary(GameSupportBase->UtilityBase);
  261.         }
  262.           CloseLibrary(&GfxBase->LibNode);
  263.         }
  264.       CloseLibrary(&IntuitionBase->LibNode);
  265.     }
  266.       CloseLibrary(&DOSBase->dl_lib);
  267.     }
  268.   BaseInitialized=FALSE;
  269. }
  270.  
  271. /************************************************************************/
  272. /*                                    */
  273. /* Initialize the library base                        */
  274. /* Note that this may break Forbid()                    */
  275. /*                                    */
  276. /************************************************************************/
  277.  
  278. static int InitLibraryBase(struct GameSupportBase *GameSupportBase)
  279.  
  280. {
  281.   if ((IntuitionBase=GameSupportBase->IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37)))
  282.     {
  283.       if (IntuitionBase->LibNode.lib_Version>=39)
  284.     {
  285.       if ((DOSBase=GameSupportBase->DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",39))!=NULL)
  286.         {
  287.           if ((GfxBase=GameSupportBase->GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",39)))
  288.         {
  289.           if ((UtilityBase=GameSupportBase->UtilityBase=OpenLibrary("utility.library",39)))
  290.             {
  291.               if ((GameSupportBase->LayersBase=OpenLibrary("layers.library",39)))
  292.             {
  293.               if ((GameSupportBase->KeymapBase=OpenLibrary("keymap.library",39))!=NULL)
  294.                 {
  295.                   LocaleBase=GameSupportBase->LocaleBase=OpenLibrary("locale.library",38);
  296.                   InitSemaphore(&GameSupportSemaphore);
  297. #if 0
  298.                   InitSemaphore(&UserlistSemaphore);
  299. #endif
  300.                   InitSemaphore(&MemorySemaphore);
  301.                   InitSemaphore(&JoystickSemaphore);
  302.                   InitSemaphore(&HappyBlankerSemaphore);
  303.                   InitSemaphore(&HappyBlankerSemaphore2);
  304.                   if ((MemoryPool=CreatePool(0,4096,4096)))
  305.                 {
  306.                   GameSupportBase->Joystick.Request.io_Device=NULL;
  307.                   BaseInitialized=TRUE;
  308.                   return TRUE;
  309.                 }
  310.                 }
  311.             }
  312.             }
  313.         }
  314.         }
  315.     }
  316.       else
  317.     {
  318.       static struct EasyStruct EasyStruct=
  319.         {
  320.           5*4,
  321.           0,
  322.           "gamesupport.library",
  323.           "gamesupport.library requires AmigaOS V39\n(Release 3.0) or any newer version",
  324.           "Quit"
  325.         };
  326.  
  327.       EasyRequestArgs(NULL,&EasyStruct,NULL,NULL);
  328.     }
  329.       CleanupLibraryBase(GameSupportBase);
  330.     }
  331.   return FALSE;
  332. }
  333.  
  334. /************************************************************************/
  335. /*                                    */
  336. /* Library open function.                        */
  337. /*                                    */
  338. /************************************************************************/
  339.  
  340. STATIC_SAVEDS_ASM_A6(struct GameSupportBase *,LibOpen,struct GameSupportBase *,GameSupportBase)
  341.  
  342. {
  343.   GameSupportBase->Library.lib_OpenCnt++;
  344.   ObtainSemaphore(&BaseSemaphore);
  345.   if (!BaseInitialized)
  346.     {
  347.       InitLibraryBase(GameSupportBase);
  348.     }
  349.   ReleaseSemaphore(&BaseSemaphore);
  350.   if (BaseInitialized)
  351.     {
  352.       GameSupportBase->Library.lib_Flags&=~LIBF_DELEXP;
  353.       return GameSupportBase;
  354.     }
  355.   GameSupportBase->Library.lib_OpenCnt--;
  356.   return NULL;
  357. }
  358.  
  359. /************************************************************************/
  360. /*                                    */
  361. /* Library expunge function.                        */
  362. /*                                    */
  363. /************************************************************************/
  364.  
  365. static BPTR MyLibExpunge(struct GameSupportBase *GameSupportBase)
  366.  
  367. {
  368.   if (GameSupportBase->Library.lib_OpenCnt)
  369.     {
  370.       GameSupportBase->Library.lib_Flags|=LIBF_DELEXP;
  371.       return MKBADDR(NULL);
  372.     }
  373.   Remove(&GameSupportBase->Library.lib_Node);
  374.   return SegList;
  375. }
  376.  
  377. /*----------------------------------------------------------------------*/
  378.  
  379. STATIC_SAVEDS_ASM_A6(BPTR,LibExpunge,struct GameSupportBase *,GameSupportBase)
  380.  
  381. {
  382.   return MyLibExpunge(GameSupportBase);
  383. }
  384.  
  385. /************************************************************************/
  386. /*                                    */
  387. /* Library close function.                        */
  388. /*                                    */
  389. /************************************************************************/
  390.  
  391. STATIC_SAVEDS_ASM_A6(BPTR,LibClose,struct GameSupportBase *,GameSupportBase)
  392.  
  393. {
  394.   GameSupportBase->Library.lib_OpenCnt--;
  395.   if (GameSupportBase->Library.lib_OpenCnt==0)
  396.     {
  397.       CleanupLibraryBase(GameSupportBase);
  398.       if (GameSupportBase->Library.lib_Flags & LIBF_DELEXP)
  399.     {
  400.       return MyLibExpunge(GameSupportBase);
  401.     }
  402.     }
  403.   return MKBADDR(NULL);
  404. }
  405.  
  406. /************************************************************************/
  407. /*                                    */
  408. /* Library dummy function.                        */
  409. /*                                    */
  410. /************************************************************************/
  411.  
  412. static ULONG LibNull(void)
  413.  
  414. {
  415.   return 0;
  416. }
  417.  
  418. /****** gamesupport.library/GS_MemoryAlloc *******************************
  419. *
  420. *   NAME
  421. *    GS_MemoryAlloc -- allocate a block of memory
  422. *
  423. *   SYNOPSIS
  424. *    Memory = GS_MemoryAlloc(Size)
  425. *      d0                     d0
  426. *
  427. *    void *GS_MemoryAlloc(ULONG);
  428. *
  429. *   FUNCTION
  430. *    Allocate a block of memory. You must call GS_MemoryFree() when
  431. *    you don't need the memory any longer.
  432. *
  433. *   INPUTS
  434. *    Size - the size of the memory block. 0 will return NULL and
  435. *        ERROR_BAD_NUMBER.
  436. *
  437. *   RESULT
  438. *    Memory - a pointer to the allocated memory, or NULL.
  439. *       In case of NULL, IoErr() will be set.
  440. *
  441. *   NOTE
  442. *    This is different from malloc(). You are responsible for freeing
  443. *    the block!
  444. *
  445. *   SEE ALSO
  446. *    GS_MemoryFree()
  447. *
  448. *************************************************************************/
  449.  
  450. SAVEDS_ASM_D0(void *,LibGS_MemoryAlloc,ULONG,Size)
  451.  
  452. {
  453.   ULONG *Memory;
  454.  
  455.   Memory=NULL;
  456.   if (Size)
  457.     {
  458.       Size+=sizeof(*Memory);
  459.       ObtainSemaphore(&MemorySemaphore);
  460.       Memory=AllocPooled(MemoryPool,Size);
  461.       ReleaseSemaphore(&MemorySemaphore);
  462.       if (Memory)
  463.     {
  464.       *(Memory++)=Size;
  465.     }
  466.       else
  467.     {
  468.       SetIoErr(ERROR_NO_FREE_STORE);
  469.     }
  470.     }
  471.   else
  472.     {
  473.       SetIoErr(ERROR_BAD_NUMBER);
  474.     }
  475.   return Memory;
  476. }
  477.  
  478. /****** gamesupport.library/GS_MemoryFree ********************************
  479. *
  480. *   NAME
  481. *    GS_MemoryFree -- free a memory block.
  482. *
  483. *   SYNOPSIS
  484. *    GS_MemoryFree(Memory)
  485. *                    a0
  486. *
  487. *    void GS_MemoryFree(void *);
  488. *
  489. *   FUNCTION
  490. *    The memory block is returned to the pool.
  491. *
  492. *   INPUTS
  493. *    Memory - the memory block. Must have been allocated by
  494. *        MemoryAlloc(). NULL is valid.
  495. *
  496. *   SEE ALSO
  497. *    GS_MemoryAlloc()
  498. *
  499. *************************************************************************/
  500.  
  501. SAVEDS_ASM_A0(void,LibGS_MemoryFree,void *,Memory)
  502.  
  503. {
  504.   if (Memory)
  505.     {
  506.       ULONG *t;
  507.  
  508.       t=Memory;
  509.       t--;
  510.       ObtainSemaphore(&MemorySemaphore);
  511.       FreePooled(MemoryPool,t,*t);
  512.       ReleaseSemaphore(&MemorySemaphore);
  513.     }
  514. }
  515.  
  516. /****** gamesupport.library/GS_MemoryRealloc *****************************
  517. *
  518. *   NAME
  519. *    GS_MemoryRealloc -- reallocate a block of memory
  520. *
  521. *   SYNOPSIS
  522. *    NewMemory = GS_MemoryRealloc(OldMemory,NewSize)
  523. *       d0                           a0        d0
  524. *
  525. *    void *GS_MemoryRealloc(void *, ULONG);
  526. *
  527. *   FUNCTION
  528. *    Reallocates a block of memory. This function will free the
  529. *    block passed in, allocate a new one and copy the old contents
  530. *    to the new block. If the new block is smaller, it copies as
  531. *    much as will fit (the rest is lost). If the new block is larger,
  532. *    the additional bytes are not initialized. If the new block has
  533. *    the same size, why did you call GS_MemoryRealloc()??
  534. *
  535. *   INPUTS
  536. *    OldMemory - the old memory block. Must have been allocated by
  537. *        GS_MemoryMalloc() or GS_MemoryRealloc(). NULL is valid:
  538. *        GS_MemoryRealloc(NULL,Size) is equivalent to
  539. *        GS_MemoryMalloc(Size).
  540. *    NewSize   - the size of the new block. 0 is valid here; it will
  541. *        return NULL and ERROR_BAD_NUMBER.
  542. *
  543. *   RESULT
  544. *    NewMemory - the new memory block. In case of NULL, the old
  545. *        pointer is still valid and must still be freed; in case
  546. *        of non-NULL, you must not use the old pointer anymore.
  547. *
  548. *   SEE ALSO
  549. *    GS_MemoryAlloc(), GS_MemoryFree(), realloc()
  550. *
  551. *************************************************************************/
  552.  
  553. SAVEDS_ASM_D0A0(void *,LibGS_MemoryRealloc,ULONG,Size,void *,Memory)
  554.  
  555. {
  556.   ULONG *NewMemory;
  557.  
  558.   NewMemory=NULL;
  559.   if (Size)
  560.     {
  561.       if (!(NewMemory=GS_MemoryAlloc(Size)))
  562.     {
  563.       return NULL;
  564.     }
  565.       if (Memory)
  566.     {
  567.       ULONG CopySize;
  568.  
  569.       CopySize=(*(((ULONG *)Memory)-1) < *(NewMemory-1)) ? *(((ULONG *)Memory)-1) : *(NewMemory-1);
  570.       CopyMemQuick(Memory,NewMemory,CopySize-sizeof(*NewMemory));
  571.     }
  572.     }
  573.   else
  574.     {
  575.       SetIoErr(ERROR_BAD_NUMBER);
  576.     }
  577.   GS_MemoryFree(Memory);
  578.   return NewMemory;
  579. }
  580.  
  581. /****** gamesupport.library/GS_TransformUsername *************************
  582. *
  583. *    NAME
  584. *    GS_TransformUsername -- transform username to filename
  585. *
  586. *    SYNOPSIS
  587. *    Filename = GS_TransformUsername(Username,OldFilename)
  588. *       d0                              a0         a1
  589. *
  590. *    char *GS_TransformUsername(const char *, char *);
  591. *
  592. *    FUNCTION
  593. *    Transform a username into something that most filesystems
  594. *    will accept as filename.
  595. *    OldFilename is a Filename that was returned from this
  596. *    function. If it is non-NULL, OldFilename will be freed
  597. *    and a new filename will be returned.
  598. *
  599. *    The intended use for this function is as follows:
  600. *
  601. *    int Success;
  602. *    char *Filename;
  603. *
  604. *    Success=FALSE;
  605. *    Filename=NULL;
  606. *    while (!Success)
  607. *      {
  608. *        Filename=GS_TransformUsername(Username,Filename);
  609. *        if (Filename==NULL)
  610. *          Error();
  611. *        File=OpenFile(Filename);
  612. *           if (File does not exist)
  613. *          Success=TRUE;
  614. *        else
  615. *          {
  616. *            FileUsername=ReadUsernameFromFile();
  617. *            if (FileUsername is equal to Username)
  618. *              Success=TRUE;
  619. *          }           
  620. *      }
  621. *
  622. *    Since the returned Filename is not unique, we read the
  623. *    Username from the file to check whether we catched the
  624. *    correct file. If we didn't, we just try the "next"
  625. *    transformation.
  626. *
  627. *    INPUTS
  628. *    Username    - the name of the user
  629. *    OldFilename - previous Filename, or NULL
  630. *
  631. *    RESULT
  632. *    Filename - a string to use as filename. NULL for error.
  633. *                  Call GS_MemoryFree(Filename) when done.
  634. *
  635. *************************************************************************/
  636.  
  637. SAVEDS_ASM_A0A1(char *,LibGS_TransformUsername,const char *,Username,char *,OldFilename)
  638.  
  639. {
  640.   if (OldFilename!=NULL)
  641.     {
  642.       unsigned char c;
  643.  
  644.       c=*(unsigned char *)OldFilename;
  645.       c=(c+1)&0x7f;
  646.       if (c<0x20)
  647.     {
  648.       c+=0x20;
  649.     }
  650.       if (c=='/' || c==':')
  651.     {
  652.       c++;
  653.     }
  654.       *(unsigned char *)OldFilename=c;
  655.       return OldFilename;
  656.     }
  657.   else
  658.     {
  659.       char *Filename;
  660.       unsigned char Sum;
  661.       int Pass;
  662.  
  663.       Sum=0;
  664.       for (Pass=0; Pass<2; Pass++)
  665.     {
  666.       union
  667.         {
  668.           LONG Length;
  669.           unsigned char *Dest;
  670.         } Param;
  671.       const unsigned char *Source;
  672.       unsigned char c;
  673.       int Space;
  674.  
  675.       if (Pass==0)
  676.         {
  677.           Param.Length=2;    /* Sum and terminating '\0' */
  678.         }
  679.       else
  680.         {
  681.           Param.Dest=(unsigned char *)Filename;
  682.           *(Param.Dest++)=Sum;
  683.         }
  684.       Space=TRUE;
  685.       for (Source=(const unsigned char *)Username; (c=*Source)!='\0'; Source++)
  686.         {
  687.           if (c=='\t')
  688.         {
  689.           c=' ';
  690.         }
  691.           if (c==' ')
  692.         {
  693.           if (!Space)
  694.             {
  695.               Space=TRUE;
  696.               if (Pass==0)
  697.             {
  698.               Param.Length++;
  699.             }
  700.               else
  701.             {
  702.               *(Param.Dest++)=c;
  703.             }
  704.             }
  705.         }
  706.           else
  707.         {
  708.           Space=FALSE;
  709.           if (Pass==0)
  710.             {
  711.               Sum+=c;
  712.             }
  713.           if (c>0x20 && c<0x80)
  714.             {
  715.               if (c!='/' && c!=':')
  716.             {
  717.               if (Pass==0)
  718.                 {
  719.                   Param.Length++;
  720.                 }
  721.               else
  722.                 {
  723.                   *(Param.Dest++)=c;
  724.                 }
  725.             }
  726.             }
  727.         }
  728.         }
  729.       if (Pass==0)
  730.         {
  731.           if ((Filename=GS_MemoryAlloc(Param.Length))==NULL)
  732.         {
  733.           Pass=2;
  734.         }
  735.           else
  736.         {
  737.           Sum&=0x7f;
  738.           if (Sum<0x20)
  739.             {
  740.               Sum+=0x20;
  741.             }
  742.           if (Sum=='/' || Sum==':')
  743.             {
  744.               Sum++;
  745.             }
  746.         }
  747.         }
  748.       else
  749.         {
  750.           *(Param.Dest)='\0';
  751.         }
  752.     }
  753.       return Filename;
  754.     }
  755.   /* not reached */
  756. }
  757.